不使用头文件在不同文件间共享变量和函数,这一切都是extern的功劳!总结要了解extern主要搞清以下几个概念:
1 声明和定义的区别。全局代码空间里,变量可以有多个声明,但只能有一个定义。
2 include头文件等同于展开头文件里的代码。
不可见字符(控制字符)与界定符(单引号、双引号、反斜框)、问号等,用一个反斜杠打头进行字符转义;
斜杠是让后面的字面转为其他的含义,不是利用其本身的含义。
C语言的强制类型转换cast:(要转换的新的数据类型)被转换的表达式;
或要转换的新的数据类型(被转换的表达式);
C语言中非0表示真。C中没有布尔类型,但你可以定义:
typedef enum{false,true} bool;
或者使用预定义
#ifndef bool #define bool int #endif #ifndef true #define true 1 #endif #ifndef false #define false 0 #endif
枚举类型是值用一组int类型的常量来定义的类型。枚举类型就像是包含一组声明常量的列表。
浮点数据的存储:符号位,指数位,小数位,也就不需要小数点了。
指针指向一个地址,该地址指向一个数据;
单精度 float:占用4字节,3字节尾数,1字节指数, 精确度7位,范围10^-38~10^38
双精度 double:占用8字节, 5字节尾数, 3字节指数, 精确度15~16位,范围10^-307~10^308
long double:占用16字节;
浮点数无法精确表示
科学计数法:尾数*10指数=尾数e指数,如123e2=12300,2.25e-3=0.00225
注意:尾数不能为空 e3要写成1e3,指数必须为整数,不能写成2.5e2.3
sizeof 运算符用来了解某一类型或某一表达式占用的内存量。sizeof 运算符的用法: sizeof(类型名) 或 sizeof(表达式) 如: sizeof(float) :float类型的变量占用的内存量 sizeof(’a’+15) :表达式 ’a’+15 的计算结果所占的内存量
左值(lvalue):在C++中,能出现在赋值运算符左边的表达式称为左值
赋值时的自动类型转换 当表达式的结果类型和变量类型不一致时,系统会将右边的表达式的结果转换成左边的变量的类型,再赋给左边的变量。
赋值和运算时的自动类型转换强制类型转换: (类型名)(表达式)或类型名 (表达式)
数据类型包括两个方面:数据的取值范围和可用的操作。
在某些应用中,不可能出现负数,则整型数中有一半的数值范围是被浪费的。因此在C/C++中可以将所有的数都看成正整数,称为无符号数。
C语言有atoi、atol、atof等库函数,可分别把ASCII编码的字符串转化为int、long、float类型的数字。
例如,在C语言中,整型类型的取值范围为-2147483648~2147483647,可用的运算集合为加、减、乘、除、取模(即+、-、*、/、%)。
一般字符占一个字节,中文及中文标点占两个字节。
为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但只在一个地方定义。
short s1 =1;
s1 = s1 + 1L;
因为s1+1L会隐式转换为L,而s1是short,所以右边表达式要强制转换:(short)(s1+1L)
如果是s1 += 1L;则+=已经执行了类型强转,所以不会出错。
正数:原码;
负数:补码:按位求反再加1;也就是模数-1,如10010的补码:11111+1-10010;简单理解就是10010取反再加1:1110
实数在内存中战占4个字节,是按照指数形式存储的,实型数据分为小数部分和指数部分:
1 小数部分:用二进制表示。
2 指数部分:用2的幂次来表示;
字符型数据:字符型数据在内存中的存储方式则按其对应的ASCII码来存储的。而所有的ASCII代码值在内存中也是以二进制形式存放的,与整形在内存中存储的方式很相似,所以这两类之间的转换也比较方便。
枚举型变量存储的是一些整数,用这些整数来代表枚举常量。
浮点数虽然可以表示很大的数,是因为其分为小数位和指数位两部分,小数位其实也就是有限的六、七位,所以其精度是较低的。
为什么需要多种整数类型:空间节省和效率的需要;
找到正确的数据表示不仅仅是选择一种数据类型,还要考虑必须进行哪些操作。也就是说,必须确定如何储存数据,并且为数据类型定义有效的操作。例如,C实现通常把int类型和指针类型都储存为整数,但是这两种类型的有效操作不相同。
例如,两个整数可以相乘,但是两个指针不相同;可以用*运算符解引用指针,但是对整数这样做豪无意义。C语言为它的基本类型都定义了有效的操作。但是,当你要设计数据表示的方案时,你可能需要自己定义有效操作。在C语言中,可以把所需的操作设计成C函数来表示。简而言之,设计一种数据类型包括设计如何储存该数据类型和设计一系管理该数据的函数。
还要注意的是,C并未很好地实现整数。例如,整数是无穷大的数,但是2字节的int类型只能表示65536个整数。因此,不要混淆抽象概念和具体的实现。
计算机科学领域已开发了一种定义新类型的好方法,用3个步骤完成从抽象到具体的过程。
1 建立抽象:提供类型属性和相关操作的抽象描述。
2 建立接口:开发一个实现ADT的编程接口。也就是说,指明如何储存数据和执行所需操作的函数。例如在C中,可以提供结构定义和操控该结构的函数原型。这些作用于用户定义类型的函数相当于作用于C基本类型的内置运算符。需要使用该新类型的程序员可以使用这个接口进行编程。
3 实现接口:编写代码实现接口。这一步至关重要,但是使用该新类型的程序员无需了解具体的实现细节。
4 使用接口。
一个数据类型通过以下几点来表征:如何构建数据?如何储存数据?有哪些可能的操作。
抽象数据类型(ADT)以抽象的方式指定构成某种类型特征的属性和操作。
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
二进制浮点数只能精确地表示多个1/2的幂的和。因此,3/4和7/8可以精确地表示为二进制小数,而1/3和2/5却不能。
在C/C++中,浮点数在默认情况下被定义为double类型。如果希望指定float类型的数值,需要在该数值后要加上字母f。
123e2=12300 2.25e-3=0.00225 注意:尾数不能为空。指数必须为整数。
枚举是具有特定值集的变量。
The C++ enum facility provides an alternative to const for creating symbolic constants. It also lets you define new types but in a fairly restricted fashion.
enum spctrum{red, orange, yellow, green, blue, violent, indgo, ultraviolet};
It establishes red, orange, yellow, and so on, as symbolic constants for the integer values 0-7. These constants are called enumerators.
spectrum band; band = blue; //valid band = 22; //invalid
int color = blue; //valid, spctrum type promoted to int
A data type is also defined in terms of the operations that can be performed on it. For example, the int type can use all the arithmetic operations. You can add, substract, multiply, and divide integers. You can also use the modulus opertor(%) with them.
When you declare a variable as an int, you're not just allocating memory-you are also establishing which operations can be performed with the variable. In short, specifying a basic type does three thing:
It determines how much memory is needed for a data object.
It determines how the bits in memory are interpreted.(A long and float might use the same number of bits in memory, but they are translated into numeric values differently.)
It determines what operations, or methods, can be performed using the data object.
“[signed] long [int]”,可以简写为“long”。
实型数据的有效数字是有限制的,利用单精度float的有效数字是6~7位,如果将数字“86041238.78”赋值给float类型,显示的数字可能是“86041240.00”,个位数“8”被四舍五入,小数位被忽略。如果将“86041238.78”与“5”相加,输出的结果为“86041245.00”,而不是“86041243.78”。
float feps = 0.0000001;
float fvar = 0.00001;
if (fvar >= -feps && fvar <=feps)
printf("等于零!\n",fvar);
默认情况下程序中出现的整数文字常量,其类型为有符号整数,即int类型。如果我们在整型文字常量的末尾添加“L”或“l”(L的大写字母或小写字母形式),则表示long整数类型。如果在整数文字常量的的末尾添加“U”或“u”(U的大写字母或小写字母形式),则表示无符号整数。
在计算机中字符是以ASCII码的形式存储的,因此,可以直接将整数赋值给字符变量。
在开发应用程序时,经常需要使用一组标记来描述对象的状态。例如一个记录集对象可以有打开状态、编辑状态和关闭状态。在程序中为了描述记录集的状态,通常定义一组常量值。
限制用户传递的参数。
枚举类型能够很好的解决上述问题,它能够将一组枚举常量与一个枚举类型名称关联。如果将函数的参数定义为某一个枚举类型,则只允许该枚举常量作为函数实际参数。
如果一个变量只有几种可能的整数值,可以一一列举出来,并希望为每一个值取一个名字代表,增加程序的可读性,则可以把该变量定义成枚举类型。
定义枚举类型的格式是:
enum <枚举类型名>
{<元素1> [= <值1> ],…,<元素名n> [ = <值n> ]}<枚举类型变量列表>;
当然也可以把枚举类型的定义和枚举变量的定义分开,在定义了枚举类型之后,以如下的格式定义枚举变量:
[enum] <枚举类型名> <枚举类型变量列表>;
enum week { sun,mon,tue,wed,thu,fri,sat,sun }day;
在算术运算和关系运算中如果参与运算的操作数类型不一样,则系统会对其进行类型转换,这是隐含转换,转换的原则就是将低类型的数据转换为高类型数据。各类型从低到高依次为char,short,int,unsigned int,long,unsigned long,float,double。类型越高范围越大,精度也越高。隐含转换是安全的,因为没有精度损失。逻辑运算符的操作数必须是bool型,如果不是就需要将其转换为bool型,非0数据转换为true,0转换为false。位运算操作数必须是整数,如果不是也会自动进行类型转换,也是低类型数据转换为高类型数据。赋值运算要求赋值运算符左边的值和右边的值类型相同,不同的话也要进行自动转换,但这个时候不会遵从上面的原则而是一律将右值转换为左值的类型。比如,int iVal; float fVal; double dVal;则dVal=iVal*fVal;计算时先将iVal转换为跟fVal一样的float型,乘法的结果再转换为double型。
强制转换:
小容器→大容器:高位补零;
大容器→小容器:高位截断;
unsigned a;
intb=-1;//每一个比特位都是1
a=b;//位照样,编码解码不一样
print(″%u\n″,a);//65535
定义性声明:需要建立存储空间的(如:int a; )声明。
引用性声明:不需建立存储空间的声明(extern a;)。
声明包括定义,但并非所有的声明都是定义。对“int a;” 而言,它既是声明,又是定义。而对“extern a;” 而言,它是声明而不是定义。
枚举:将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。
typedef int NUM[100];
NUM n;
int add(int a,int b){
return (a+b); }
typedef int (* func)(int ,int ) ;
func f = add;
typedef,在定义复合类型时,直接将变量做为一种类型变量;
用typedef定义类型的方法:
①先按定义变量的方法写出定义体(如:int i)。
②将变量名换成新类型名(例如:将i换成COUNT)。
③在最前面加typedef(例如:typedef int COUNT)。
④然后可以用新类型名去定义变量。
int add();
typedef int (*pf)();
pf f = add;
强制类型转换的目的之一:抑制警告信息;
在许多情况下,强制类型转换告诉编译器,“是的,我真的想这样做。”这指示编译器,即使有数据损失或其他危险的可能性,也继续执行数据转换。强制类型转换也可以用来澄清模糊的情况。
Qualifier Modifier Type Identifier = literal
qualifier: unsigned, signed, long, short
Modifier: const, volitile, restrict
Type: int, char, bool, enum, float, double, union, struct, objcet
literal: 215u, 0xFeeL, 0213, 0x4b, 30ul, 314159E-5L, true, false, \n, \ooo, \xhh . . ."hello, dear", "hello, \dear", "hello, " "d" "ear"
extern const long double d = 314159E-5L;
// [Declaration] [Qualifier] [Modifier] Type Identifier = literal
逻辑型数据与其他数据类型的关系
1、逻辑型数据作为数值数据使用时,false转换为0,true转换为1。
2、字符型、枚举型、整型或实型数据值作为逻辑值使用时,一切0值转换成false,一切非0值转换成true。
3、指针值作为逻辑值使用时,空指针值转换成false,非空指针值转换成true。
总结:0就是false,非0就是true。
整数提升(Integer promotion)指的是一种类型转换规则:某些类型的表达式被隐式地转换为int 类型或unsigned int 类型。
构成C 源程序的词汇或单词(token)一共有5 种:关键字(Keyword)、标识符(Identifier)、常量(Constant)、字符串字面量(String-Literal)和标点符号(Punctuator)。而并非只有标识符这样一种。
"a"、'a'与a 都是构成C 代码的基本单词(Token)。
"a"是一个字符串文字量(String Literal),其中含有一个字符a 和一个编码为0 的字符;
'a'是一个int 类型的常量(constant),其值为“a”这个字符的编码值,通常被称为字符常量,尽管它不是char 类型;
而a 则是一个标识符(Identifier)。
char c=255;
printf("%d\n",c);
在Visual C++系统上进行编译时,系统给出“警告”(warning):“把一个整常数赋给char 变量”。表示255 已超过char 变量的数值允许值,在运行时输出?1。说明Visual C++是把char 默认为signed char 类型的。如果把第1 行改为“unsigned char c=255;”,则不出现“警告”,且 输出255。
char 类型数据的范围的定义:
CHAR_MIN、CHAR_MAX,根据char 类型数据的最大、最小值,很容易了解char 类型数据是否有符号。
实数是一个数学概念,包括有理数和无理数?浮点数显然不能表示无理数。有理数中又包括整数和分数(或等价的小数),浮点数显然无法表示分数。即使把浮点数看成可以表示小数,它也不可能表示所有小数,因为有一类小数叫无限循环小数,浮点数绝对无法表示。
浮点数用来近似表示某个具体范围内的实数。
浮点数则是按照某种记数规则(浮点数表示方法)所表示的数,它所能表示的只是有理数的一个有限子集。在计算机中,浮点数除了用来近似地表示某个范围内的实数,还有一些特殊值,比如NaN、inf、-inf 等(表示非数值、正负无穷)。计算机中的浮点数只有有限个。
由此可见,浮点数和实数完全不是对等的概念,甚至不是同一个层次上的概念。不能把它们混为一谈。
在计算机中,浮点数只能近似地表示值在某个范围之内的有理数或一些特殊值。
如果一个运算符两侧的数据类型不同,则先自动进行类型转换,使两者具有同一类型,然后进行运算。
unsigned char a=64; printf("%d %d\n",a<<1,a<<2); // integer promotion
浮点数,小数点可以浮点,实际没有使用小数点,123.4可以表示为1.234e2,也可以表示为12.34e1,看起来好像浮点了,其实浮点数在内存中的表示将全部位分为3部分,1位的符号位,剩下的位分配给尾数与指数。
指数采用移码,尾数使用直接码。
1 整数的内存表达
1.1 内存的布局与格式;
1.2 整数范围;
2 整数的操作规则
2.1 算子;
2.2 溢出规则;
2.3 异常处理规则;
3 整数和其他数据类型(如浮点数)的替换规则
3.1 小数点舍去规则;
3.2 整数转换成其他类(如浮点数)的规则;
存储类型:extern、static
类型限定符:const、volatile、register
类型修饰符:unsigned、long、short
类型:int、float、double、char
C编程语言中的变量是指定的存储器位置,用户可以在程序执行期间存储相同数据类型的不同值。这意味着变量是给予内存位置的名称,我们可以在其中存储相同数据类型的不同值。换句话说,变量可以定义为在程序执行期间保存相同数据类型值的存储容器。数据类型的正式定义如下......
When doing division with two integers (called integer division), C++ always produces an integer result. Since integers can’t hold fractional values, any fractional portion is simply dropped (not rounded!).
Much like an integer can vary in size depending on the system, size_t also varies in size. size_t is guaranteed to be unsigned and at least 16 bits, but on most systems will be equivalent to the address-width of the application. That is, for 32-bit applications, size_t will typically be a 32-bit unsigned integer, and for a 64-bit application, size_t will typically be a 64-bit unsigned integer. size_t is defined to be big enough to hold the size of the largest object creatable on your system (in bytes). For example, if size_t is 4 bytes, the largest object creatable on your system can’t be larger than the largest number representable by a 4-byte unsigned integer (per the table above, 4,294,967,295 bytes).
Some languages, notably BASIC, create a new variable whenever you use a new name, withoutthe aid of explicit declarations. That might seem friendlier to the user, and it is—in theshort term. The problem is that if you misspell the name of a variable, you inadvertently can create a new variable without realizing it.
The wchar_t type is an integer type with sufficient space to represent the largest extended character set used on the system.This type has the same size and sign properties as one of the other integer types, which is called the underlying type.The choice of underlying type depends on the implementation, so it could be unsigned short on one system and int on another.